﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Diagnostics;
using System.Linq;
using System.Xml.Linq;
using System.Globalization;
using System.IO;
using System.IO.IsolatedStorage;
using System.Windows.Media.Imaging;

namespace DailyBread
{
    public class PanoramaBG
    {
        private static readonly Uri PhotoImagesUri = new Uri("http://feeds.feedburner.com/bingimages");
        private static readonly Uri BuildInImageUri = new Uri("images/sunset.jpg", UriKind.Relative);

        public static ImageBrush GetImage()
        {
            IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication();
            BitmapImage bmpImg = new BitmapImage();

            string imgnm = Util.GetShortNavUrl(System.DateTime.Today) + ".jpg";

            if (isoStore.FileExists(imgnm))
            {
                    using (IsolatedStorageFileStream isoStream = isoStore.OpenFile(imgnm, FileMode.Open))
                    {
                        bmpImg.SetSource(isoStream);
                    }

            }
            else
            {
                // use yesterday's image
                string lastImg = Util.GetShortNavUrl(System.DateTime.Today.AddDays(-1)) + ".jpg";

                if (isoStore.FileExists(lastImg))
                {
                    using (IsolatedStorageFileStream isoStream = isoStore.OpenFile(lastImg, FileMode.Open))
                    {
                        bmpImg.SetSource(isoStream);
                    }

                }
                else
                {
                    // use stock image
                    bmpImg.UriSource = BuildInImageUri;
                }

                // kick off the async call to retrieve the image from web
                GetBingImage(
                    delegate(Uri imageUri)
                    {
                        WebClient wc = new WebClient();
                        wc.OpenReadCompleted += new OpenReadCompletedEventHandler(wc_OpenReadCompleted);
                        wc.OpenReadAsync(imageUri);
                    });
                
            }
            return new ImageBrush { ImageSource = bmpImg};
        }

        public static void FetchImage(Action<ImageBrush> SetImageSrc)
        {
            using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication())
            {
                BitmapImage bmpImg = new BitmapImage();

                string imgnm = Util.GetShortNavUrl(System.DateTime.Today) + ".jpg";

                if (isoStore.FileExists(imgnm))
                {
                    using (IsolatedStorageFileStream isoStream = isoStore.OpenFile(imgnm, FileMode.Open))
                    {
                        bmpImg.SetSource(isoStream);

                        // call back to set the image
                        ImageBrush imgBrush = new ImageBrush { ImageSource = bmpImg };
                        Deployment.Current.Dispatcher.BeginInvoke(() => { SetImageSrc(imgBrush); });
                        return;
                    }

                }
            }

            GetBingImage(
               delegate(Uri imageUri)
               {
                   WebClient wc = new WebClient();
                   wc.OpenReadCompleted += delegate(object sender, OpenReadCompletedEventArgs e)
                   {
                       if (e.Error == null)
                       {
                           IsolatedStorageFile isof = IsolatedStorageFile.GetUserStoreForApplication();
                           try
                           {
                               bool? chkRes = CheckAndGetMoreSpace(e.Result.Length);
                               if (chkRes == false)
                               {
                                   throw new Exception("Cannot store image due to insufficient space");
                               }
                               string imgName = Util.GetShortNavUrl(System.DateTime.Today) + ".jpg";
                               BitmapImage bmpImage = new BitmapImage();

                               // Save the image to Isolated Storage
                               using (IsolatedStorageFileStream isfs = new IsolatedStorageFileStream(imgName, FileMode.Create, isof))
                               {
                                   Int64 imgLen = (Int64)e.Result.Length;
                                   byte[] b = new byte[imgLen];
                                   e.Result.Read(b, 0, b.Length);
                                   isfs.Write(b, 0, b.Length);
                                   isfs.Flush();

                                   
                                   bmpImage.SetSource(isfs);

                                   isfs.Close();
                               }

                               // delete cached image from 2 days ago if it exists
                               imgName = Util.GetShortNavUrl(System.DateTime.Today.AddDays(-2)) + ".jpg";

                               if (isof.FileExists(imgName))
                               {
                                   isof.DeleteFile(imgName);
                               }

                               // call back to set the image
                               ImageBrush imgBrush = new ImageBrush { ImageSource = bmpImage };
                               Deployment.Current.Dispatcher.BeginInvoke(() => { SetImageSrc(imgBrush); });
                           }
                           catch (Exception ex)
                           {
                               Debug.WriteLine(ex.ToString());
                           }
                           finally
                           {
                               isof.Dispose();
                           }
                       }
                   };
                   wc.OpenReadAsync(imageUri);
               });
        }

        private static void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
        {

            if (e.Error == null)
            {

                try
                {

                    IsolatedStorageFile isof = IsolatedStorageFile.GetUserStoreForApplication();

                    bool? chkRes = CheckAndGetMoreSpace(e.Result.Length);

                    if (chkRes == false)
                    {

                        throw new Exception("Cannot store image due to insufficient space");

                    }



                    string imgName = Util.GetShortNavUrl(System.DateTime.Today) + ".jpg";



                    // Save the image to Isolated Storage

                    IsolatedStorageFileStream isfs = new IsolatedStorageFileStream(imgName, FileMode.Create, isof);

                    Int64 imgLen = (Int64)e.Result.Length;

                    byte[] b = new byte[imgLen];

                    e.Result.Read(b, 0, b.Length);

                    isfs.Write(b, 0, b.Length);

                    isfs.Flush();



                    isfs.Close();

                    // delete cached image from 2 days ago if it exists
                    string imgnm = Util.GetShortNavUrl(System.DateTime.Today.AddDays(-2)) + ".jpg";

                    if (isof.FileExists(imgnm))
                    {
                        isof.DeleteFile(imgnm);
                    }

                    isof.Dispose();
                }

                catch (Exception ex)
                {

                    Debug.WriteLine(ex.ToString());

                }

            }

        }



        // Increase Isolated Storage Quota

        protected static bool CheckAndGetMoreSpace(Int64 spaceReq)
        {

            IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication();

            Int64 spaceAvail = store.AvailableFreeSpace;

            if (spaceReq > spaceAvail)
            {

                if (!store.IncreaseQuotaTo(store.Quota + spaceReq))
                {

                    return false;

                }

                return true;

            }

            return true;

        }

        public static void GetBingImage(Action<Uri> SetBackground)
        {
            Uri imageUri = null;

            // WebClient is slow since its all on the UI thread but for this
            // sample its OK with me!
            //WebClient wc = new WebClient();
            //wc.DownloadStringCompleted += (x, xe) =>
            try
            {
                Debug.WriteLine("\nstart to fetch bing image at " + System.DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.ffff"));
                HttpService.Get(PhotoImagesUri,
                    delegate(string results)
                    {
                        try
                        {
                            XDocument doc = XDocument.Parse(results);
                            var items = doc.Element("rss")
                                           .Element("channel")
                                           .Elements("item")
                                           .ToList();
                            string countryCode = CultureInfo.CurrentUICulture.Name.ToUpperInvariant();
                            var urls = items
                                .Where(s =>
                                       s.Element("enclosure")
                                        .Attribute("url")
                                        .Value
                                        .Contains("_" + countryCode)
                                       ||
                                       s.Element("enclosure")
                                        .Attribute("url")
                                        .Value
                                        .Contains("_EN-US")
                                        )
                                .Select(p =>
                                    p.Element("enclosure")
                                     .Attribute("url")
                                     .Value)
                                .ToList();
                            if (urls.Count > 0)
                            {
                                imageUri = new Uri(urls[0]);
                                Deployment.Current.Dispatcher.BeginInvoke(() => { SetBackground(imageUri); });
                            }
                            else
                            {
                                Deployment.Current.Dispatcher.BeginInvoke(() => { SetBackground(BuildInImageUri); });
                            }
                        }
                        catch (Exception ex)
                        {
                            Debug.WriteLine(ex.ToString());
                            Deployment.Current.Dispatcher.BeginInvoke(() => { SetBackground(BuildInImageUri); });
                        }

                    },
                    delegate(string uriString, Exception ex)
                    {
                        Debug.WriteLine(ex.ToString());
                        Deployment.Current.Dispatcher.BeginInvoke(() => { SetBackground(BuildInImageUri); });
                    });
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
                Deployment.Current.Dispatcher.BeginInvoke(() => { SetBackground(BuildInImageUri); });
            }
       }
    }
}
